// 如何用 new 运算符从构造器中得到一个对象

function Person (name) {
    this.name = name;
}

Person.prototype.getName = function () {
    return this.name;
};

var a = new Person('sven');

console.log(a.name);         // sven
console.log(a.getName());    // sven
console.log(Object.getPrototypeOf(a) === Person.prototype); // true


// 在 Chrome 和 Firefox 等向外暴露了对象 __proto__ 属性的浏览器下，可以通过下面这段代码来理解 new 运算的过程
function Person (name) {
    this.name = name;
}

Person.prototype.getName = function () {
    return this.name;
};

var objectFactory = function () {
    var obj = new Object(), // 从 Object.prototype 上克隆一个空的对象
        Constructor = [].shift.call(arguments); // 取得外部传入的构造器，此例是 Person
    
    obj.__proto__ = Constructor.prototype; // 指向正确的原型
    var ret = Constructor.apply(obj, arguments); // 借用外部传入的构造器给 obj 设置属性

    return typeof ret === 'object' ? ret : obj; // 确保构造器总是返回一个对象
};

var a = objectFactory(Person, 'sven');

console.log(a.name);         // sven
console.log(a.getName());    // sven
console.log(Object.getPrototypeOf(a) === Person.prototype); // true

// 一样的结构
var a = objectFactory(A, 'sven');
var a = new A('sven');